package system

import (
	"goweb/examples/gfiber/gmiddleware"
	"goweb/web/global"
	"goweb/web/model/common/request"
	"goweb/web/model/common/response"
	"goweb/web/model/system"
	userReq "goweb/web/model/system/request"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/golang-jwt/jwt/v4"
	"go.uber.org/zap"
)

// 定义接口
type User struct {
}

func (b *User) Create(c *fiber.Ctx) error {
	var user userReq.UserCreateRequest
	if err := c.BodyParser(&user); err != nil {
		return response.FailWithMessage("请求体解析失败", c)
	}
	if u, err := userService.Create(user); err != nil {
		return response.FailWithMessage(err.Error(), c)
	} else {
		return response.Result(global.StatusOK, u, "操作成功", c)
	}
}

func (b *User) Update(c *fiber.Ctx) error {
	var user system.User
	if err := c.BodyParser(&user); err != nil {
		return response.FailWithMessage("请求体解析失败", c)
	}
	if u, err := userService.Update(user); err != nil {
		return response.FailWithMessage(err.Error(), c)
	} else {
		return response.Result(global.StatusOK, u, "操作成功", c)
	}
}

// List接口
func (b *User) List(c *fiber.Ctx) error {
	if list, err := userService.List(); err != nil {
		return response.FailWithMessage(err.Error(), c)
	} else {
		return response.Result(global.StatusOK, list, "操作成功", c)
	}
}

func (b *User) Page(c *fiber.Ctx) error {
	// 解析请求参数
	var userPage userReq.UserPageRequest
	if err := c.BodyParser(&userPage); err != nil {
		global.LOG.Error("请求体解析失败: %s", zap.Any("err", err))
		return response.FailWithMessage("请求体解析错误", c)
	}

	if list, total, err := userService.Page(userPage); err != nil {
		global.LOG.Error("获取失败!", zap.Any("err", err))
		return response.FailWithMessage("请求失败", c)
	} else {
		return response.Result(global.StatusOK, response.PageResult{
			Data:     list,
			Total:    total,
			PageNum:  userPage.PageInfo.PageNum,
			PageSize: userPage.PageInfo.PageSize,
		}, "操作成功", c)
	}
}

// 根据uuid 获取详情
func (b *User) GetInfo(c *fiber.Ctx) error {
	uuid := c.Params("uuid")

	err, u := userService.GetById(uuid)
	if err != nil {
		global.LOG.Error(err.Error())
		return response.FailWithMessage("查询失败", c)
	}
	return response.SuccessWithData(u, c)
}

// 根据uuid 删除用户信息
func (b *User) Delete(c *fiber.Ctx) error {
	uuid := c.Params("uuid")

	if err := userService.DeleteById(uuid); err != nil {
		global.LOG.Error(err.Error())
		return response.FailWithMessage("删除失败", c)
	}
	return response.Success(c)
}

// 根据uuids 批量删除
func (b *User) BatchDelete(c *fiber.Ctx) error {
	var userBatchDel userReq.UserBatchDeleteRequest
	if err := c.BodyParser(&userBatchDel); err != nil {
		global.LOG.Error("请求体解析失败: %s", zap.Any("err", err))
		return response.FailWithMessage("请求体解析错误", c)
	}

	uuids := userBatchDel.Uuids
	if err := userService.DeleteBatchByUuid(uuids); err != nil {
		global.LOG.Error(err.Error())
		return response.FailWithMessage("批量删除失败", c)
	}
	return response.Success(c)
}

// 登录
func (b *User) Login(c *fiber.Ctx) error {
	var loginReq request.LoginRequest
	if err := c.BodyParser(&loginReq); err != nil {
		global.LOG.Error("请求体解析失败: %s", zap.Any("err", err))
		return response.FailWithMessage("请求体解析错误", c)
	}

	u := &system.User{Username: loginReq.Username, Password: loginReq.Password}
	if user, err := userService.Login(u); err != nil {
		global.LOG.Error("登陆失败! 用户名不存在或者密码错误!", zap.Any("err", err))
		return response.FailWithMessage("用户名不存在或者密码错误", c)
	} else {
		return b.tokenNext(c, *user)
	}
}

// 登录以后签发jwt
func (b *User) tokenNext(c *fiber.Ctx, user system.User) error {
	j := &gmiddleware.JWT{SigningKey: []byte(global.Config.Jwt.SigningKey)} // 唯一签名
	var expiresTime = global.Config.Jwt.ExpiresTime
	claims := request.TokenClaims{
		UUID:     user.Uuid,
		ID:       user.ID,
		Nickname: user.NickName,
		Username: user.Username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(expiresTime) * time.Minute)), // 过期时间 30分钟 配置文件
			IssuedAt:  jwt.NewNumericDate(time.Now()),                                               // 签发时间
		},
	}
	// 生成 token
	accessToken, err := j.CreateToken(claims)
	// 生成 refresh token
	refreshToken, rtErr := j.CreateToken(request.RefreshTokenClaims{
		ID:   user.ID,
		Uuid: user.Uuid,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(1) * time.Hour)), // 过期时间 1小时
			IssuedAt:  jwt.NewNumericDate(time.Now()),                                   // 签发时间
		},
	})
	if err != nil || rtErr != nil {
		global.LOG.Error("设置登录状态失败!", zap.Any("err", err))
		return response.FailWithMessage("设置登录状态失败", c)
	}
	return response.Result(global.StatusOK, response.LoginResponse{
		User:         user,
		Token:        accessToken,
		RefreshToken: refreshToken,
	}, "登录成功", c)
}

// 退出
func (b *User) Logout(c *fiber.Ctx) error {
	// 清除 token
	return nil
}

// 刷新token: 重新生成token
func (b *User) RefreshToken(c *fiber.Ctx) error {
	var refreshToken request.RefreshToken
	if err := c.BodyParser(&refreshToken); err != nil {
		return response.FailWithMessage("请求体解析错误", c)
	}

	// 创建 jwt对象
	j := gmiddleware.NewJWT()

	// 解析token
	tc, err := j.ParseToken(refreshToken.RefreshToken)
	if err != nil {
		return response.Result(global.ExpireRefreshToken, fiber.Map{"reload": true}, err.Error(), c)
	}

	if err, u := userService.GetById(tc.UUID); err != nil {
		return response.FailWithMessage("用户名不存在或者密码错误", c)
	} else {
		return b.tokenNext(c, u)
	}
}
